#ifndef __KEW_H__
#define __KEW_H__
#ifdef __cplusplus
extern "C" {
#endif

#include <glib.h>

typedef struct _KewObject KewObject;
typedef struct _KewObjectType KewObjectType;
typedef struct _KewDispatchMap KewDispatchMap;
typedef void (*KewMethod)(KewObject *receiver,
                          KewObject *args[],
                          KewObject *results[]);


struct _KewObject {
  KewObjectType *type;
  KewObject *context[0];
};

struct _KewDispatchMap {
  char *selector;
  KewMethod method;
  unsigned argument_cardinality;
  unsigned result_cardinality;
};

struct _KewObjectType {
  char *source_file_name;
  unsigned line_number;
  unsigned context_slots;
  KewDispatchMap dispatch_map[0];
};

extern void Kew__GenericFinalize(KewObject *object);



extern void KewInit(void);

extern char *KewVersion(void);

extern char *KewCopyright();


/* Predefined built-in objects.  WARNING: this must agree with the
   list used by the compiler's symbol table. */

#define KewNil (KewBuiltin[0])
#define KewTrue (KewBuiltin[1])
#define KewFalse (KewBuiltin[2])
#define KewEmptySet (KewBuiltin[3])
#define KewEmptyList (KewBuiltin[4])
#define KewList (KewBuiltin[4]) /* Deprecated */
#define KewEmptyMap (KewBuiltin[5])
#define KewMap (KewBuiltin[5]) /* Deprecated */
#define KewVariable (KewBuiltin[6])
#define KewVar (KewBuiltin[6]) /* Deprecated */
#define KewException (KewBuiltin[7])
#define KewContinuationAlreadyTaken (KewBuiltin[8])
#define KewMissingKey (KewBuiltin[9])
#define KewMissingMethod (KewBuiltin[10])
#define KewWrongObjectType (KewBuiltin[11])
#define KewDefaultExceptionHandler (KewBuiltin[12])
#define KewPrimitives (KewBuiltin[13])
#define KEW_NUMBER_OF_BUILTINS 14
extern KewObject *KewBuiltin[KEW_NUMBER_OF_BUILTINS];


extern void KewSend(KewObject *receiver,
                    char *selector,
                    KewObject *args[],
                    unsigned number_of_args,
                    KewObject *results[],
                    unsigned number_of_results,
                    char *source_file_name,
                    unsigned line_number);

extern void KewPrintStackTrace(void);

extern KewObject *KewCheckType(KewObject *object, KewObjectType *object_type, char *type_name);

extern void KewLoadComponent(char *path, 
                             char *component_name,
                             KewObject *args[],
                             unsigned number_of_args,
                             KewObject *results[],
                             unsigned number_of_results);

extern KewObject * KewNewObjectFull(KewObjectType *type,
                                    unsigned context_size);

extern KewObject *KewNewObject(KewObjectType *type);

extern KewObject *KewNewBlock(KewMethod method,
                              unsigned argument_cardinality,
                              unsigned result_cardinality,
                              unsigned context_size);

extern KewObject *KewNewVar(KewObject *initial_value);




/* Lists */

extern KewObjectType KewListType;

extern KewObject *KewNewList(GList *l);

extern KewObject *KewWrapList(GList *l);

extern KewObject *KewNewListFromArray(KewObject *array[], unsigned array_size);

extern KewObject *KewListFor(KewObject *list, KewObject *initial, KewObject *block);


/* Maps */

extern KewObject *KewNewMap(GHashTable *h);


/* I/O Channels */

extern KewObject *KewNewIOChannel(GIOChannel *channel);

extern KewObject *KewNewUnixIOChannel(int fd);


/* Messages (reflected) */

extern KewObject *KewNewMessage(KewObject *receiver,
                                KewObject *selector,
                                KewObject *arguments);

extern KewObject *KewNewMessageRaw(KewObject *receiver,
                                   char *selector,
                                   KewObject *args[],
                                   unsigned args_size);


/* Ranges */

extern KewObjectType KewRangeType;

extern KewObject *KewNewRange(KewObject *from, KewObject *to);

extern KewObject *KewRangeFor(KewObject *list, KewObject *initial, KewObject *block);


/* Integers */

extern KewObjectType KewIntType;

extern KewObject *KewNewInt(int i);

extern gint KewIntVal(KewObject *object);


/* Booleans */

#define KewNewBool(expr) ((expr) ? KewTrue : KewFalse)

extern gboolean KewBoolVal(KewObject *object);

#define KewIsTrue(expr) ((expr) == KewTrue)

#define KewIsFalse(expr) ((expr) == KewFalse)


/* Strings */

extern KewObject *KewNewString(char *s);

extern KewObject *KewWrapString(char *s);

extern KewObject *KewWrapStringArray(char *strings[], unsigned number_of_strings);

extern char *KewStringVal(KewObject *object);


/* Reals */

extern KewObject *KewNewReal(double d);

extern double KewRealVal(KewObject *object);


/* Nil */

#define KewIsNil(expr) ((expr) == KewNil)



#ifdef __cplusplus
}
#endif
#endif
